package com.example.auth.web;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.util.IOUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.io.IOException;
import java.util.Map;

/** @author yang */
@Slf4j
@Controller
public class CodeClientController {

  /**
   * 用来展示index.html 模板
   *
   * @return
   */
  @GetMapping(value = "index")
  public String index() {
    return "index";
  }

  @GetMapping(value = "login")
  public Object login(String code, Model model) {
      if(null == code){
        return "index";
      }
      String tokenUrl = "http://localhost:2000/oauth/token";
      OkHttpClient httpClient = new OkHttpClient();
      RequestBody body =
          new FormBody.Builder()
              .add("grant_type", "authorization_code")
              .add("client", "code-client")
              .add("redirect_uri", "http://localhost:2020/client-authcode/login")
              .add("code", code)
              .build();

      Request request =
          new Request.Builder()
              .url(tokenUrl)
              .post(body)
              .addHeader("Authorization", "Basic Y29kZS1jbGllbnQ6Y29kZS1zZWNyZXQtODg4OA==")
              .build();
      try {
        Response response = httpClient.newCall(request).execute();
        String result = response.body().string();
        ObjectMapper objectMapper = new ObjectMapper();
        Map tokenMap = objectMapper.readValue(result, Map.class);
        String accessToken = JSONUtil.parseObj(tokenMap.get("data")).getStr("token");

        Resource resource = new ClassPathResource("public.key");
        String publicKey = null;
        try {
          publicKey = IOUtils.toString(resource.getInputStream());
        } catch (final IOException e) {
          throw new RuntimeException(e);
        }

        RsaVerifier rsaVerifier = new RsaVerifier(publicKey);
        Jwt jwt = JwtHelper.decodeAndVerify(accessToken, rsaVerifier);
        String claims =  jwt.getClaims();
        JSONObject userJsonObject = new JSONObject(claims);
        String userName = userJsonObject.getStr("user_name");
        model.addAttribute("username", userName);
        model.addAttribute("accessToken", result);
      return "index";
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @org.springframework.web.bind.annotation.ResponseBody
  @GetMapping(value = "get")
  @PreAuthorize("hasAnyRole('ROLE_ADMIN')")
  public Object get(Authentication authentication) {
    // Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    authentication.getCredentials();
    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
    String token = details.getTokenValue();
    return token;
  }
}
